package org.rayson.server;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;

import org.rayson.api.Protocol;
import org.rayson.api.server.exception.DuplicateServiceException;
import org.rayson.api.server.exception.ServiceException;
import org.rayson.server.transport.ServerSelector;
import org.rayson.share.transport.NioSelector;

public class Server {

	private final Container container;

	private int portNumber;

	private ServerSelector selector;

	private final ServerConfig config;

	public Server(final int portNumber) {
		this(portNumber, new ServerConfig());
	}

	protected Server(final int portNumber, final ServerConfig config) {
		super();
		this.portNumber = portNumber;
		this.config = config;
		this.container = new Container(config, this);
	}

	public Container getContainer() {
		return container;
	}

	public String getName() {

		return "Rayson server on " + this.portNumber;
	}

	NioSelector getSelector() {
		return selector;
	}

	/**
	 * @param testService
	 * @throws DuplicateServiceException
	 * @throws ServiceException
	 */
	public void registerService(final Protocol service)
			throws DuplicateServiceException, ServiceException {
		this.container.getServiceManager().register(service);
	}

	public void start() throws IOException {
		final ServerSocketChannel socketChannel = ServerSocketChannel.open();
		socketChannel.configureBlocking(false);
		final InetSocketAddress socketAddress = new InetSocketAddress(
				this.portNumber);
		socketChannel.socket().bind(socketAddress);
		this.portNumber = socketAddress.getPort();
		try {
			this.container.start(null);
		} catch (final Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		this.selector = new ServerSelector(Selector.open(), getName(),
				socketChannel, container);
		this.selector.start(null);

	}

	@Override
	public String toString() {
		return getName();
	}
}